package com.atguigu.gmall.item.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.product.ProductSkuDetailFeignCilent;
import com.atguigu.gmall.feign.search.SearchFeignCilent;
import com.atguigu.gmall.item.service.SkuDetailService;
import com.atguigu.gmall.item.vo.SkuDetailVo;
import com.atguigu.gmall.product.entity.SkuImage;
import com.atguigu.gmall.product.entity.SkuInfo;
import com.atguigu.gmall.product.entity.SpuSaleAttr;
import com.atguigu.gmall.search.vo.SearchParamVo;
import com.atguigu.gmall.starter.cache.aspect.annotation.MallCache;
import com.atguigu.gmall.starter.cache.service.CacheService;
import com.atguigu.gmall.weball.vo.CategoryTreeVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description
 * @Return
 * @Author https://weiranyi.github.io
 * @Date Created in 2022-12-03 20:48
 **/
@Slf4j
@Service
public class SkuDetailServiceImpl implements SkuDetailService {
    @Autowired
    ProductSkuDetailFeignCilent skuDetailFeignCilent;
    @Autowired
    ThreadPoolExecutor coreExecutor;
    @Autowired
    CacheService cacheService;
    // 引入Redisson
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    SearchFeignCilent searchFeignCilent;

    //JUC：本地锁；在分布式场景，会导致锁不住所有机器；
    ReentrantLock lock = new ReentrantLock(); //原理：AQS、CAS

    // 通过AOP对核心业务进行增强&采用分布式锁的方式
    @MallCache(
            cacheKey = RedisConst.CACHE_SKU_DETAIL_PREFIX + "#{#args[0]}",
            bitmapName = RedisConst.BITMAP_SKU_NAME,
            bitmapKey = "#{#args[0]}",
            lockKey = RedisConst.LOCK_SKU_PREFIX + "#{#args[0]}",
            ttl = 7,
            unit = TimeUnit.DAYS
    )
    @Override
    public SkuDetailVo getSkuDetailData(Long skuId) {
        // 这儿写核心的业务逻辑
        return getSkuDetailVoFromRPC(skuId);
    }

    @Override
    public void autoIncrementHotScore(Long skuId) {
        CompletableFuture.runAsync(() -> {
            // ES 增加热度分
            Long increment = redisTemplate.opsForValue().increment(RedisConst.CACHE_SKU_HOTSCORE + skuId);
            if (increment % 100 == 0) {
                searchFeignCilent.autoIncrementHotScore(skuId, increment);
            }
        }, coreExecutor);

    }

    //    public SkuDetailVo getSkuDetailDataDistribution(Long skuId) {
    //        SkuDetailVo skuDetailVoReturnVal = null;
    //        // 1.查询缓存
    //        skuDetailVoReturnVal = cacheService.getFromCache(skuId);
    //        // 2. 缓存有
    //        if (skuDetailVoReturnVal != null) {
    //            return skuDetailVoReturnVal;
    //        }
    //        // 3.缓存没有，判断位图是否有
    //        Boolean contain = cacheService.mightContain(skuId);
    //        // 3.1位图说没有
    //        if (!contain) {
    //            return null;
    //        }
    //        // 3.2位图说有，准备回源
    //        // 拦截击穿风险------------------------------
    //        RLock lock = redissonClient.getLock(RedisConst.LOCK_SKU_PREFIX + skuId);
    //        boolean tryLock = false;
    //        try {
    //            tryLock = lock.tryLock();
    //            if (tryLock) {
    //                // 回源
    //                skuDetailVoReturnVal = getSkuDetailVoFromRPC(skuId);
    //                cacheService.setToCache(skuId, skuDetailVoReturnVal);
    //                return skuDetailVoReturnVal;
    //            } else {
    //                try {
    //                    TimeUnit.MICROSECONDS.sleep(500);
    //                    return cacheService.getFromCache(skuId);
    //                } catch (InterruptedException e) {
    //                    e.printStackTrace();
    //                }
    //            }
    //        } finally {
    //            if (tryLock) {
    //                try {
    //                    lock.unlock();
    //                } catch (Exception e) {
    //
    //                }
    //            }
    //        }
    //        return skuDetailVoReturnVal;
    //    }

    // 本地锁的方式
    //    public SkuDetailVo getSkuDetailDataByLocalLock(Long skuId) {
    //        log.info("开始查询商品详情。。。");
    //        SkuDetailVo skuDetailVoReturnVal = null;
    //        // 1.查缓存
    //        skuDetailVoReturnVal = cacheService.getFromCache(skuId);
    //        if (skuDetailVoReturnVal == null) { //这里可以判断是真空，还是假空
    //            // 2.判断位图是否有
    //            Boolean contain = cacheService.mightContain(skuId);
    //            if (!contain) {
    //                log.info("bitmap没有，疑似攻击请求，直接打回");
    //                return null;
    //            }
    //            //拦截击穿风险----------------------------
    //            boolean tryLock = lock.tryLock();
    //            if (tryLock) {
    //                log.info("抢锁成功，开始回源···");
    //                // 3.缓存没有，位图说有，开始回源
    //                skuDetailVoReturnVal = getSkuDetailVoFromRPC(skuId);
    //                cacheService.setToCache(skuId, skuDetailVoReturnVal);
    //                lock.unlock();
    //            } else {
    //                try {
    //                    log.info("抢锁失败，等待缓存有值，开始睡觉···");
    //                    TimeUnit.MICROSECONDS.sleep(500);
    //                    skuDetailVoReturnVal = cacheService.getFromCache(skuId);
    //                } catch (InterruptedException e) {
    //                    e.printStackTrace();
    //                }
    //            }
    //            //拦截完成-------------------------------
    //            cacheService.setToCache(skuId, skuDetailVoReturnVal);
    //        }
    //        return skuDetailVoReturnVal;
    //    }

    private SkuDetailVo getSkuDetailVoFromRPC(Long skuId) {
        SkuDetailVo skuDetailVo = new SkuDetailVo();

        // 1.商品详情 图片！  SkuInfo skuInfo = skuDetailFeignCilent.getSkuInfo(skuId).getData();
        CompletableFuture<SkuInfo> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfo skuInfo = skuDetailFeignCilent.getSkuInfo(skuId).getData();
            return skuInfo;
        }, coreExecutor);
        // 2.商品图片 skuInfo.setSkuImageList(skuImageList);
        CompletableFuture<Void> imageAsync = skuInfoCompletableFuture.thenAcceptAsync((skuInfoByResult) -> {
            if (skuInfoByResult == null) return;
            List<SkuImage> skuImageList = skuDetailFeignCilent.getSkuImages(skuId).getData();
            skuInfoByResult.setSkuImageList(skuImageList);
            skuDetailVo.setSkuInfo(skuInfoByResult);
        }, coreExecutor);
        // 3.精确的分级信息
        CompletableFuture<Void> categoryAsync = skuInfoCompletableFuture.thenAcceptAsync((skuInfoByResult) -> {
            if (skuInfoByResult == null) return;
            CategoryTreeVo categoryTreeVo = skuDetailFeignCilent.getCategoryTreeVoByC3Id(skuInfoByResult.getCategory3Id()).getData();
            // 数据模型转换
            SkuDetailVo.CategoryView categoryView = convertToCategoryView(categoryTreeVo);
            skuDetailVo.setCategoryView(categoryView);
        }, coreExecutor);

        // 4.实时价格
        CompletableFuture<Void> priceAsync = CompletableFuture.runAsync(() -> {
            try {
                BigDecimal price = skuDetailFeignCilent.getPrice(skuId).getData();
                skuDetailVo.setPrice(price);
            } catch (Exception e) {

            }
        }, coreExecutor);

        // 5.销售属性
        CompletableFuture<Void> spuSaleAsync = skuInfoCompletableFuture.thenAcceptAsync((skuInfoByResult) -> {
            if (skuInfoByResult == null) return;
            List<SpuSaleAttr> spuSaleAttrs = skuDetailFeignCilent.getSpuSaleAttr(skuInfoByResult.getSpuId(), skuId).getData();
            skuDetailVo.setSpuSaleAttrList(spuSaleAttrs);
        }, coreExecutor);

        // 6.ValuesSkuJson
        CompletableFuture<Void> valuesSkuJsonAsync = skuInfoCompletableFuture.thenAcceptAsync((skuInfoByResult) -> {
            if (skuInfoByResult == null) return;
            String valuesSkuJson = skuDetailFeignCilent.getValuesSkuJson(skuInfoByResult.getSpuId()).getData();
            skuDetailVo.setValuesSkuJson(valuesSkuJson);
        }, coreExecutor);
        CompletableFuture.allOf(imageAsync, categoryAsync, priceAsync, spuSaleAsync, valuesSkuJsonAsync).join(); //插队在主线程前

        return skuDetailVo;
    }

    private SkuDetailVo.CategoryView convertToCategoryView(CategoryTreeVo categoryTreeVo) {
        SkuDetailVo.CategoryView categoryView = new SkuDetailVo.CategoryView();
        //一级
        Long category1Id = categoryTreeVo.getCategoryId();
        String category1Name = categoryTreeVo.getCategoryName();
        //二级
        CategoryTreeVo category2TreeVo = categoryTreeVo.getCategoryChild().get(0);
        Long category2Id = category2TreeVo.getCategoryId();
        String category2Name = category2TreeVo.getCategoryName();
        //三级
        CategoryTreeVo category3TreeVo = category2TreeVo.getCategoryChild().get(0);
        Long category3Id = category3TreeVo.getCategoryId();
        String category3Name = category3TreeVo.getCategoryName();
        categoryView.setCategory1Id(category1Id);
        categoryView.setCategory2Id(category2Id);
        categoryView.setCategory3Id(category3Id);
        categoryView.setCategory1Name(category1Name);
        categoryView.setCategory2Name(category2Name);
        categoryView.setCategory3Name(category3Name);
        return categoryView;
    }
}
